package com.neardrug.utils;

import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.neardrug.common.Constants;
import com.neardrug.entity.*;
import com.neardrug.exception.ServiceException;
import com.neardrug.mapper.FormTableMapper;
import com.neardrug.mapper.NumeratorMapper;
import com.neardrug.system.StaticProvider;
import com.neardrug.system.StringMultipartFile;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.net.ssl.SSLContext;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Path;
import java.util.*;

/**
 * 用于处理api的返回结果
 */
@Slf4j
public class ApiUtil {
    private static final NumeratorMapper numeratorMapper= StaticProvider.getNumeratorMapper();

    public static void test(String test){
        log.info("-------------------------");
        log.info(test);
        log.info("-------------------------");
    }

    public static Record recordDeal(String recordResult){
        //log.info("Entering recordDeal method");

        JSONObject recordObject = new JSONObject(recordResult);

        String Abstract=recordObject.optString("Abstract","");
        JSONArray applicants = recordObject.optJSONArray("Applicants");
        JSONObject cpc_number = recordObject.optJSONObject("CPC_number");
        JSONArray disease = recordObject.optJSONArray("Disease");
        JSONArray genes = recordObject.optJSONArray("Genes");
        JSONObject ipc_number = recordObject.optJSONObject("IPC_number");
        String kind_code = recordObject.optString("Kind code","");
        JSONArray mutations = recordObject.optJSONArray("Mutations");
        String pct_pub_no = recordObject.optString("PCT_Pub_No","");
        String pct_pub_date = recordObject.optString("PCT_Pub_date","");
        String pct_application_data = recordObject.optString("PCT_application_data","");
        String pct_number = recordObject.optString("PCT_number", "");
        JSONObject prior_publication = recordObject.optJSONObject("Prior_publication");
        JSONArray agents = recordObject.optJSONArray("agents");
        String application_number = recordObject.optString("application_number");
        String date_of_patent = recordObject.optString("date_of_patent");
        String filing_date = recordObject.optString("filing_date");
        JSONArray inventors = recordObject.optJSONArray("inventors");
        String patent_number = recordObject.optString("patent_number");
        String pub_date = recordObject.optString("pub_date");
        String pub_number = recordObject.optString("pub_number");
        String title = recordObject.optString("title");


        Record record=Record.builder()
                .Abstract(Abstract)
                .applicants(applicants!=null ? applicants.toString() : null)
                .cpcNumber(cpc_number!=null ? cpc_number.toString() : null)
                .disease(disease!=null ? disease.toString() : null)
                .genes(genes!=null ? genes.toString() : null)
                .ipcNumber(ipc_number!=null ? ipc_number.toString() : null)
                .kindCode(kind_code)
                .mutations(mutations!=null ? mutations.toString() : null)
                .pctPubNo(pct_pub_no)
                .pctPubDate(pct_pub_date)
                .pctApplicationData(pct_application_data)
                .pctNumber(pct_number)
                .priorPublication(prior_publication!=null ? prior_publication.toString() : null)
                .agents(agents!=null ? agents.toString() : null)
                .applicationNumber(application_number)
                .dateOfPatent(date_of_patent)
                .filingDate(filing_date)
                .inventors(inventors!=null ? inventors.toString() : null)
                .patentNumber(patent_number)
                .pubDate(pub_date)
                .pubNumber(pub_number)
                .title(title)
                .recordResult(recordResult)
                .build();

        return record;
    }

    /**
     * 用于处理api返回的example_data中的数据
     * @param exampleResult
     */
    public static String exampleDeal1(String exampleResult,String fileNameWithoutExtension){
        MultipartFile multipartFile=new StringMultipartFile("file",fileNameWithoutExtension+"-examples.json","application/json",exampleResult);
        //try(CloseableHttpClient client = HttpClients.createDefault()) {
        try (CloseableHttpClient client = createHttpClient()) {
            String exampleApiUrl="https://lilab.ecust.edu.cn/chemdata_extract";
            HttpPost post = new HttpPost(exampleApiUrl);
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            ContentBody contentBody = new ByteArrayBody(multipartFile.getBytes(), multipartFile.getOriginalFilename());
            builder.addPart("file",contentBody);
            post.setEntity(builder.build());
            HttpResponse response=client.execute(post);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode==200){
                // 读取响应体
                BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
                StringBuilder responseBody = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    responseBody.append(line);
                }
                // 获取原始JSON字符串
                String apiResult = responseBody.toString();
                return apiResult;
            }else {
                throw new ServiceException(Constants.CODE_500,"文件分析有误");
            }
        } catch (IOException e) {
            throw new ServiceException(Constants.CODE_500,"文件分析有误");
        }

    }

    /**
     * 用于细节处理example的api返回的数据
     * @param jsonArray
     * @return
     */
    public static List<Synthesis> exampleDeal2(JSONArray jsonArray){

        List<Synthesis> synthesisList=new ArrayList<>();

        for (int i = 0; i < jsonArray.length(); i++) {
            //得到每一个example信息
            JSONObject jsonObject = jsonArray.getJSONObject(i);

            JSONObject figuresObject=jsonObject.optJSONObject("figures");
            JSONArray array = jsonObject.optJSONArray("example_ner_result");
            if (array!=null){//如果确实有example_ner_result的数据
                Object o=array.opt(0);

                JSONObject exampleNerResult=new JSONObject(o.toString());
                String exampleId=exampleNerResult.optString("example_Id","null");//获取到exampleId
                //判断这个example_Id是否是合法的
                String regex = "^Example ?\\d+$";//定义正则表达式
                if (exampleId.matches(regex)){
                    exampleId=exampleId.replace(" ","");
                    Integer flag = judgeIfExist(synthesisList, exampleId);//判断现在这个exampleId的synthesis是否存在
                    if (flag==-1){//说明现在这个exampleId的synthesis不存在
                        //准备ChemicalCompound的相关数据(1)
                        String compoundId=exampleNerResult.optString("compound_id","");
                        String intermediateName = exampleNerResult.optString("intermediate_name", "");
                        String compoundName = exampleNerResult.optString("compoundName", "");
                        JSONArray smiles = figuresObject.optJSONArray("SMILES");
                        String referenceReactions=exampleNerResult.optString("reference_reactions","");
                        String HNMR = exampleNerResult.optString("H_NMR", "");
                        String CNMR = exampleNerResult.optString("C_NMR", "");
                        String FNMR = exampleNerResult.optString("F_NMR", "");
                        String PNMR = exampleNerResult.optString("P_NMR", "");
                        String MS = exampleNerResult.optString("MS", "");
                        String IR = exampleNerResult.optString("IR", "");
                        String UV = exampleNerResult.optString("UV", "");
                        String Mp = exampleNerResult.optString("Mp", "");
                        String Rf = exampleNerResult.optString("Rf", "");
                        String AnalCalcd = exampleNerResult.optString("Anal.calcd", "");
                        String LCMS = exampleNerResult.optString("LC-MS", "");
                        String HPLC = exampleNerResult.optString("HPLC", "");
                        //准备ChemicalCompound的相关数据(2:NER_structured_step_Desc的数据)
                        JSONObject nerStructuredStepDesc = exampleNerResult.optJSONObject("NER_structured_step_Desc");
                        if (nerStructuredStepDesc==null){//如果这个键没有信息，那么构建对象的时候就少构建一些信息
                            //构建ChemicalCompound并准备塞入List中
                            ChemicalCompound chemicalCompound=ChemicalCompound.builder()
                                    .exampleId(exampleId)
                                    .compoundId(compoundId)
                                    .intermediateName(intermediateName)
                                    .compoundName(compoundName)
                                    .smiles(smiles.toString())
                                    .referenceReactions(referenceReactions)
                                    .HNMR(HNMR)
                                    .CNMR(CNMR)
                                    .FNMR(FNMR)
                                    .PNMR(PNMR)
                                    .MS(MS)
                                    .IR(IR)
                                    .UV(UV)
                                    .Mp(Mp)
                                    .Rf(Rf)
                                    .AnalCalcd(AnalCalcd)
                                    .LCMS(LCMS)
                                    .HPLC(HPLC)
                                    .build();
                            Synthesis synthesis=Synthesis.builder()
                                    .chemicalCompound(chemicalCompound)
                                    .synthesisProcessList(new ArrayList<>())
                                    .build();
                            synthesisList.add(synthesis);
                        }else {//如果与exampleid同级的确实有这个数据
                            // 使用 JsonParser 解析 JSON 字符串
                            JsonObject nerStructuredStepDescObject = JsonParser.parseString(nerStructuredStepDesc.toString()).getAsJsonObject();
                            // 提取不同键的值
                            JsonElement EXAMPLELABELElement = nerStructuredStepDescObject.get("EXAMPLE_LABEL");
                            JsonElement REACTIONPRODUCTElement = nerStructuredStepDescObject.get("REACTION_PRODUCT");
                            JsonElement STARTINGMATERIALElement = nerStructuredStepDescObject.get("STARTING_MATERIAL");
                            JsonElement REAGENTCATALYSTElement = nerStructuredStepDescObject.get("REAGENT_CATALYST");
                            JsonElement SOLVENTElement = nerStructuredStepDescObject.get("SOLVENT");
                            JsonElement TIMESElement = nerStructuredStepDescObject.get("TIMES");
                            JsonElement TEMPERATUREElement = nerStructuredStepDescObject.get("TEMPERATURE");
                            JsonElement YIELDPERCENTElement = nerStructuredStepDescObject.get("YIELD_PERCENT");
                            JsonElement YIELDOTHERElement = nerStructuredStepDescObject.get("YIELD_OTHER");
                            JsonElement OTHERCOMPOUNDElement = nerStructuredStepDescObject.get("OTHER_COMPOUND");

                            String EXAMPLELABEL=judgeIfIsString(EXAMPLELABELElement);
                            String REACTIONPRODUCT=judgeIfIsString(REACTIONPRODUCTElement);
                            String STARTINGMATERIAL=judgeIfIsString(STARTINGMATERIALElement);
                            String REAGENTCATALYST=judgeIfIsString(REAGENTCATALYSTElement);
                            String SOLVENT=judgeIfIsString(SOLVENTElement);
                            String TIMES=judgeIfIsString(TIMESElement);
                            String TEMPERATURE=judgeIfIsString(TEMPERATUREElement);
                            String YIELDPERCENT=judgeIfIsString(YIELDPERCENTElement);
                            String YIELDOTHER=judgeIfIsString(YIELDOTHERElement);
                            String OTHERCOMPOUND=judgeIfIsString(OTHERCOMPOUNDElement);

                            ChemicalCompound chemicalCompound=ChemicalCompound.builder()
                                    .exampleId(exampleId)
                                    .compoundId(compoundId)
                                    .intermediateName(intermediateName)
                                    .compoundName(compoundName)
                                    .smiles(smiles.toString())
                                    .referenceReactions(referenceReactions)
                                    .HNMR(HNMR)
                                    .CNMR(CNMR)
                                    .FNMR(FNMR)
                                    .PNMR(PNMR)
                                    .MS(MS)
                                    .IR(IR)
                                    .UV(UV)
                                    .Mp(Mp)
                                    .Rf(Rf)
                                    .AnalCalcd(AnalCalcd)
                                    .LCMS(LCMS)
                                    .HPLC(HPLC)
                                    .EXAMPLELABEL(EXAMPLELABEL)
                                    .REACTIONPRODUCT(REACTIONPRODUCT)
                                    .STARINGMATERIAL(STARTINGMATERIAL)
                                    .REAGENTCATALYST(REAGENTCATALYST)
                                    .SOLVENT(SOLVENT)
                                    .TIMES(TIMES)
                                    .TEMPERATURE(TEMPERATURE)
                                    .YIELDPERCENT(YIELDPERCENT)
                                    .YIELDOTHER(YIELDOTHER)
                                    .OTHERCOMPOUND(OTHERCOMPOUND)
                                    .build();
                            Synthesis synthesis=Synthesis.builder()
                                    .chemicalCompound(chemicalCompound)
                                    .synthesisProcessList(new ArrayList<>())
                                    .build();
                            synthesisList.add(synthesis);
                        }
                    }

                    //然后 根据exampleId往这个Synthesis中塞入SynthesisProcess的数据
                    //得到这个exampleId对应的synthesis在List中的下标
                    Integer synthesisIndex=getSynthesisByExampleId(synthesisList, exampleId);
                    if (synthesisIndex!=-1){//几乎无用的判断 肯定不为-1

                        //得到list中指定索引位置的synthesis
                        Synthesis synthesis = synthesisList.get(synthesisIndex);
                        List<SynthesisProcess> synthesisProcessList = synthesis.getSynthesisProcessList();

                        //判断多种step的情况：
                        //如果没有step或steps这两个键
                        if (exampleNerResult.optJSONArray("step")==null && exampleNerResult.optJSONArray("steps")==null){
                            String stepCompound=exampleNerResult.optString("step_Compound","");
                            String stepDesc=exampleNerResult.optString("step_Desc","");
                            SynthesisProcess synthesisProcess=SynthesisProcess.builder()
                                    .stepCompound(stepCompound)
                                    .stepDesc(stepDesc)
                                    .build();
                            //将这个synthesisProcess加入synthesislist
                            synthesisProcessList.add(synthesisProcess);
                            //更新原来的synthesis
                            synthesis.setSynthesisProcessList(synthesisProcessList);
                            //更新synthesisList指定位置的synthesis值
                            synthesisList.set(synthesisIndex,synthesis);
                        }else if (exampleNerResult.optJSONArray("step")!=null){
                            //如果有step这个键
                            JSONArray stepData=exampleNerResult.optJSONArray("step");
                            for (int j = 0; j < stepData.length(); j++) {
                                //获取到每一项
                                JSONObject stepObject=stepData.getJSONObject(j);

                                JSONObject nerStructuredStepDesc = exampleNerResult.optJSONObject("NER_structured_step_Desc");
                                if (nerStructuredStepDesc==null){//如果这个键没有信息，那么构建对象的时候就少构建一些信息
                                    String stepId=stepObject.optString("step_Id","");
                                    String stepCompound=stepObject.optString("step_Compound","");
                                    String stepDesc=stepObject.optString("step_Desc","");
                                    String referenceReactions=stepObject.optString("reference_reactions","");
                                    String proHNMR=stepObject.optString("H_NMR","");
                                    String proCNMR=stepObject.optString("C_NMR","");
                                    String proFNMR=stepObject.optString("F_NMR","");
                                    String proPNMR=stepObject.optString("P_NMR","");
                                    String proMS=stepObject.optString("MS","");
                                    String proIR=stepObject.optString("IR","");
                                    String proUV=stepObject.optString("UV","");
                                    String proMp=stepObject.optString("Mp","");
                                    String proRf=stepObject.optString("Rf","");
                                    String proAnalCalcd=stepObject.optString("Anal.calcd","");
                                    String proLCMS=stepObject.optString("LC-MS","");
                                    String proHPLC=stepObject.optString("HPLC","");
                                    SynthesisProcess synthesisProcess=SynthesisProcess.builder()
                                            .stepId(stepId)
                                            .stepCompound(stepCompound)
                                            .stepDesc(stepDesc)
                                            .proReferenceReactions(referenceReactions)
                                            .proHNMR(proHNMR)
                                            .proCNMR(proCNMR)
                                            .proFNMR(proFNMR)
                                            .proPNMR(proPNMR)
                                            .proMS(proMS)
                                            .proIR(proIR)
                                            .proUV(proUV)
                                            .proMp(proMp)
                                            .proRf(proRf)
                                            .proAnalCalcd(proAnalCalcd)
                                            .proLCMS(proLCMS)
                                            .proHPLC(proHPLC)
                                            .build();
                                    //将这个synthesisProcess加入synthesislist
                                    synthesisProcessList.add(synthesisProcess);
                                    //更新原来的synthesis
                                    synthesis.setSynthesisProcessList(synthesisProcessList);
                                }else {//如果确实有这个数据
                                    // 使用 JsonParser 解析 JSON 字符串
                                    JsonObject nerStructuredStepDescObject = JsonParser.parseString(nerStructuredStepDesc.toString()).getAsJsonObject();
                                    // 提取不同键的值
                                    JsonElement EXAMPLELABELElement = nerStructuredStepDescObject.get("EXAMPLE_LABEL");
                                    JsonElement REACTIONPRODUCTElement = nerStructuredStepDescObject.get("REACTION_PRODUCT");
                                    JsonElement STARTINGMATERIALElement = nerStructuredStepDescObject.get("STARTING_MATERIAL");
                                    JsonElement REAGENTCATALYSTElement = nerStructuredStepDescObject.get("REAGENT_CATALYST");
                                    JsonElement SOLVENTElement = nerStructuredStepDescObject.get("SOLVENT");
                                    JsonElement TIMESElement = nerStructuredStepDescObject.get("TIMES");
                                    JsonElement TEMPERATUREElement = nerStructuredStepDescObject.get("TEMPERATURE");
                                    JsonElement YIELDPERCENTElement = nerStructuredStepDescObject.get("YIELD_PERCENT");
                                    JsonElement YIELDOTHERElement = nerStructuredStepDescObject.get("YIELD_OTHER");
                                    JsonElement OTHERCOMPOUNDElement = nerStructuredStepDescObject.get("OTHER_COMPOUND");
                                    String EXAMPLELABEL=judgeIfIsString(EXAMPLELABELElement);
                                    String REACTIONPRODUCT=judgeIfIsString(REACTIONPRODUCTElement);
                                    String STARTINGMATERIAL=judgeIfIsString(STARTINGMATERIALElement);
                                    String REAGENTCATALYST=judgeIfIsString(REAGENTCATALYSTElement);
                                    String SOLVENT=judgeIfIsString(SOLVENTElement);
                                    String TIMES=judgeIfIsString(TIMESElement);
                                    String TEMPERATURE=judgeIfIsString(TEMPERATUREElement);
                                    String YIELDPERCENT=judgeIfIsString(YIELDPERCENTElement);
                                    String YIELDOTHER=judgeIfIsString(YIELDOTHERElement);
                                    String OTHERCOMPOUND=judgeIfIsString(OTHERCOMPOUNDElement);
                                    String stepId=stepObject.optString("step_Id","");
                                    String stepCompound=stepObject.optString("step_Compound","");
                                    String stepDesc=stepObject.optString("step_Desc","");
                                    String referenceReactions=stepObject.optString("reference_reactions","");
                                    String proHNMR=stepObject.optString("H_NMR","");
                                    String proCNMR=stepObject.optString("C_NMR","");
                                    String proFNMR=stepObject.optString("F_NMR","");
                                    String proPNMR=stepObject.optString("P_NMR","");
                                    String proMS=stepObject.optString("MS","");
                                    String proIR=stepObject.optString("IR","");
                                    String proUV=stepObject.optString("UV","");
                                    String proMp=stepObject.optString("Mp","");
                                    String proRf=stepObject.optString("Rf","");
                                    String proAnalCalcd=stepObject.optString("Anal.calcd","");
                                    String proLCMS=stepObject.optString("LC-MS","");
                                    String proHPLC=stepObject.optString("HPLC","");
                                    SynthesisProcess synthesisProcess=SynthesisProcess.builder()
                                            .stepId(stepId)
                                            .stepCompound(stepCompound)
                                            .stepDesc(stepDesc)
                                            .proReferenceReactions(referenceReactions)
                                            .proHNMR(proHNMR)
                                            .proCNMR(proCNMR)
                                            .proFNMR(proFNMR)
                                            .proPNMR(proPNMR)
                                            .proMS(proMS)
                                            .proIR(proIR)
                                            .proUV(proUV)
                                            .proMp(proMp)
                                            .proRf(proRf)
                                            .proAnalCalcd(proAnalCalcd)
                                            .proLCMS(proLCMS)
                                            .proHPLC(proHPLC)
                                            .proEXAMPLELABEL(EXAMPLELABEL)
                                            .proREACTIONPRODUCT(REACTIONPRODUCT)
                                            .proSTARINGMATERIAL(STARTINGMATERIAL)
                                            .proREAGENTCATALYST(REAGENTCATALYST)
                                            .proSOLVENT(SOLVENT)
                                            .proTIMES(TIMES)
                                            .proTEMPERATURE(TEMPERATURE)
                                            .proYIELDPERCENT(YIELDPERCENT)
                                            .proYIELDOTHER(YIELDOTHER)
                                            .proOTHERCOMPOUND(OTHERCOMPOUND)
                                            .build();
                                    //将这个synthesisProcess加入synthesislist
                                    synthesisProcessList.add(synthesisProcess);
                                    //更新原来的synthesis
                                    synthesis.setSynthesisProcessList(synthesisProcessList);
                                }
                            }
                            //更新synthesisList指定位置的synthesis值
                            synthesisList.set(synthesisIndex,synthesis);
                        }else if (exampleNerResult.optJSONArray("steps")!=null){
                            //如果有steps这个键
                            JSONArray stepData=exampleNerResult.optJSONArray("steps");
                            for (int j = 0; j < stepData.length(); j++) {
                                //获取到每一项
                                JSONObject stepObject=stepData.getJSONObject(j);

                                JSONObject nerStructuredStepDesc = exampleNerResult.optJSONObject("NER_structured_step_Desc");
                                if (nerStructuredStepDesc==null){//如果这个键没有信息，那么构建对象的时候就少构建一些信息
                                    String stepId=stepObject.optString("step_Id","");
                                    String stepCompound=stepObject.optString("step_Compound","");
                                    String stepDesc=stepObject.optString("step_Desc","");
                                    String referenceReactions=stepObject.optString("reference_reactions","");
                                    String proHNMR=stepObject.optString("H_NMR","");
                                    String proCNMR=stepObject.optString("C_NMR","");
                                    String proFNMR=stepObject.optString("F_NMR","");
                                    String proPNMR=stepObject.optString("P_NMR","");
                                    String proMS=stepObject.optString("MS","");
                                    String proIR=stepObject.optString("IR","");
                                    String proUV=stepObject.optString("UV","");
                                    String proMp=stepObject.optString("Mp","");
                                    String proRf=stepObject.optString("Rf","");
                                    String proAnalCalcd=stepObject.optString("Anal.calcd","");
                                    String proLCMS=stepObject.optString("LC-MS","");
                                    String proHPLC=stepObject.optString("HPLC","");
                                    SynthesisProcess synthesisProcess=SynthesisProcess.builder()
                                            .stepId(stepId)
                                            .stepCompound(stepCompound)
                                            .stepDesc(stepDesc)
                                            .proReferenceReactions(referenceReactions)
                                            .proHNMR(proHNMR)
                                            .proCNMR(proCNMR)
                                            .proFNMR(proFNMR)
                                            .proPNMR(proPNMR)
                                            .proMS(proMS)
                                            .proIR(proIR)
                                            .proUV(proUV)
                                            .proMp(proMp)
                                            .proRf(proRf)
                                            .proAnalCalcd(proAnalCalcd)
                                            .proLCMS(proLCMS)
                                            .proHPLC(proHPLC)
                                            .build();
                                    //将这个synthesisProcess加入synthesislist
                                    synthesisProcessList.add(synthesisProcess);
                                    //更新原来的synthesis
                                    synthesis.setSynthesisProcessList(synthesisProcessList);
                                }else {//如果确实有这个数据
                                    // 使用 JsonParser 解析 JSON 字符串
                                    JsonObject nerStructuredStepDescObject = JsonParser.parseString(nerStructuredStepDesc.toString()).getAsJsonObject();
                                    // 提取不同键的值
                                    JsonElement EXAMPLELABELElement = nerStructuredStepDescObject.get("EXAMPLE_LABEL");
                                    JsonElement REACTIONPRODUCTElement = nerStructuredStepDescObject.get("REACTION_PRODUCT");
                                    JsonElement STARTINGMATERIALElement = nerStructuredStepDescObject.get("STARTING_MATERIAL");
                                    JsonElement REAGENTCATALYSTElement = nerStructuredStepDescObject.get("REAGENT_CATALYST");
                                    JsonElement SOLVENTElement = nerStructuredStepDescObject.get("SOLVENT");
                                    JsonElement TIMESElement = nerStructuredStepDescObject.get("TIMES");
                                    JsonElement TEMPERATUREElement = nerStructuredStepDescObject.get("TEMPERATURE");
                                    JsonElement YIELDPERCENTElement = nerStructuredStepDescObject.get("YIELD_PERCENT");
                                    JsonElement YIELDOTHERElement = nerStructuredStepDescObject.get("YIELD_OTHER");
                                    JsonElement OTHERCOMPOUNDElement = nerStructuredStepDescObject.get("OTHER_COMPOUND");

                                    String EXAMPLELABEL=judgeIfIsString(EXAMPLELABELElement);
                                    String REACTIONPRODUCT=judgeIfIsString(REACTIONPRODUCTElement);
                                    String STARTINGMATERIAL=judgeIfIsString(STARTINGMATERIALElement);
                                    String REAGENTCATALYST=judgeIfIsString(REAGENTCATALYSTElement);
                                    String SOLVENT=judgeIfIsString(SOLVENTElement);
                                    String TIMES=judgeIfIsString(TIMESElement);
                                    String TEMPERATURE=judgeIfIsString(TEMPERATUREElement);
                                    String YIELDPERCENT=judgeIfIsString(YIELDPERCENTElement);
                                    String YIELDOTHER=judgeIfIsString(YIELDOTHERElement);
                                    String OTHERCOMPOUND=judgeIfIsString(OTHERCOMPOUNDElement);

                                    String stepId=stepObject.optString("step_Id","");
                                    String stepCompound=stepObject.optString("step_Compound","");
                                    String stepDesc=stepObject.optString("step_Desc","");
                                    String referenceReactions=stepObject.optString("reference_reactions","");
                                    String proHNMR=stepObject.optString("H_NMR","");
                                    String proCNMR=stepObject.optString("C_NMR","");
                                    String proFNMR=stepObject.optString("F_NMR","");
                                    String proPNMR=stepObject.optString("P_NMR","");
                                    String proMS=stepObject.optString("MS","");
                                    String proIR=stepObject.optString("IR","");
                                    String proUV=stepObject.optString("UV","");
                                    String proMp=stepObject.optString("Mp","");
                                    String proRf=stepObject.optString("Rf","");
                                    String proAnalCalcd=stepObject.optString("Anal.calcd","");
                                    String proLCMS=stepObject.optString("LC-MS","");
                                    String proHPLC=stepObject.optString("HPLC","");
                                    SynthesisProcess synthesisProcess=SynthesisProcess.builder()
                                            .stepId(stepId)
                                            .stepCompound(stepCompound)
                                            .stepDesc(stepDesc)
                                            .proReferenceReactions(referenceReactions)
                                            .proHNMR(proHNMR)
                                            .proCNMR(proCNMR)
                                            .proFNMR(proFNMR)
                                            .proPNMR(proPNMR)
                                            .proMS(proMS)
                                            .proIR(proIR)
                                            .proUV(proUV)
                                            .proMp(proMp)
                                            .proRf(proRf)
                                            .proAnalCalcd(proAnalCalcd)
                                            .proLCMS(proLCMS)
                                            .proHPLC(proHPLC)
                                            .proEXAMPLELABEL(EXAMPLELABEL)
                                            .proREACTIONPRODUCT(REACTIONPRODUCT)
                                            .proSTARINGMATERIAL(STARTINGMATERIAL)
                                            .proREAGENTCATALYST(REAGENTCATALYST)
                                            .proSOLVENT(SOLVENT)
                                            .proTIMES(TIMES)
                                            .proTEMPERATURE(TEMPERATURE)
                                            .proYIELDPERCENT(YIELDPERCENT)
                                            .proYIELDOTHER(YIELDOTHER)
                                            .proOTHERCOMPOUND(OTHERCOMPOUND)
                                            .build();
                                    //将这个synthesisProcess加入synthesislist
                                    synthesisProcessList.add(synthesisProcess);
                                    //更新原来的synthesis
                                    synthesis.setSynthesisProcessList(synthesisProcessList);
                                }
                            }
                            //更新synthesisList指定位置的synthesis值
                            synthesisList.set(synthesisIndex,synthesis);
                        }
                    }
                }
            }
        }
        return synthesisList;
    }

    //判断在SynthesisList中，指定exampleId的Synthesis是否存在
    public static Integer judgeIfExist(List<Synthesis> synthesisList,String exampleId){
        if (synthesisList.size()==0){
            return -1;
        }else {//如果synthesisList里确实有数据
            for (int i = 0; i < synthesisList.size(); i++) {
                Synthesis synthesis = synthesisList.get(i);
                ChemicalCompound chemicalCompound = synthesis.getChemicalCompound();
                String id = chemicalCompound.getExampleId();
                if (id.equals(exampleId)){
                    return i;//返回这个synthesis在list中的索引
                }
            }
            return -1;
        }
    }

    /**
     * 根据exampleId得到这个synthesis在synthesisList中的索引
     * @param synthesisList
     * @param exampleId
     * @return
     */
    public static Integer getSynthesisByExampleId(List<Synthesis> synthesisList,String exampleId){
        for (int i = 0; i < synthesisList.size(); i++) {
            Synthesis synthesis=synthesisList.get(i);
            ChemicalCompound chemicalCompound = synthesis.getChemicalCompound();
            if (chemicalCompound.getExampleId().equals(exampleId)){
                return i;
            }
        }
        return -1;
    }

    /**
     * 判断传递的JsonElement是不是字符串类型 如果确实是字符串类型那么就转为字符串
     * @param jsonElement
     * @return
     */
    public static String judgeIfIsString(JsonElement jsonElement){
        if (jsonElement != null && jsonElement.isJsonPrimitive() && jsonElement.getAsJsonPrimitive().isString()) {
            return jsonElement.getAsString();
        }else {
            return "";
        }
    }

    public static List<Images> middle2images(Integer taskId,JSONArray jsonArray){
        //最终要插入数据库的所有Images对象
        List<Images> imagesList=new ArrayList<>();

        //获取到page_info中每一个对象(每个对象表示每页的信息)
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject jsonObject = jsonArray.getJSONObject(i);
            JSONArray imagesArray = jsonObject.optJSONArray("images");
            //如果这个页面里面确实提取到了图片 那么再继续分析提取
            if (imagesArray.length()!=0){
                //遍历这个页面中的所有图片
                for (int j = 0; j < imagesArray.length(); j++) {
                    Images image=new Images();//最后用于插入数据库的images
                    String caption="";
                    String img="";
                    String footnote="";
                    Integer label=-1;
                    JSONObject images=imagesArray.getJSONObject(j);
                    JSONArray blocksArray = images.optJSONArray("blocks");
                    //遍历一张图片的blocks(包含image_body,可能包含image_caption,image_footnote)
                    for (int k = 0; k < blocksArray.length(); k++) {
                        //得到每个block
                        JSONObject blockObject = blocksArray.getJSONObject(k);
                        if (blockObject.optString("type","").equals("image_body")){//如果是image_body
                            JSONArray lines = blockObject.optJSONArray("lines");//得到lines数组
                            Images images1 = lines2Image(lines);
                            image.setImg(images1.getImg());
                            image.setLabel(images1.getLabel());
                        }else if (blockObject.optString("type","").equals("image_caption")){//如果是image_caption
                            JSONArray lines = blockObject.optJSONArray("lines");//得到lines数组
                            Images images2 = lines2Caption(lines);
                            image.setCaption(images2.getCaption());
                        }else if (blockObject.optString("type","").equals("image_footnote")){//如果是image_footnote
                            JSONArray lines = blockObject.optJSONArray("lines");//得到lines数组
                            Images images3 = lines2Footnote(lines);
                            image.setFootnote(images3.getFootnote());
                        }
                    }
                    if (image.getLabel()!=-1){
                        image.setTaskId(taskId);
                        imagesList.add(image);
                    }
                }
            }
        }
        return imagesList;
    }

    /**
     * 已知type为image_body 根据lines得到image的相关数据(image_base64_str,label)
     * @param lines
     * @return
     */
    public static Images lines2Image(JSONArray lines){
        String img="";
        Integer label=-1;
        if (lines.length()!=0){
            JSONObject linesObject = lines.getJSONObject(0);//得到lines的json对象
            JSONArray spans = linesObject.optJSONArray("spans");
            if (spans.length()!=0){
                JSONObject spansObject = spans.getJSONObject(0);//得到spans的json对象
                //得到图片的base64编码值
                img=spansObject.optString("image_base64_str","");
                JSONArray imageClassification = spansObject.optJSONArray("image_classification");
                if (imageClassification.length()!=0){
                    JSONObject imageClassificationObject = imageClassification.getJSONObject(0);
                    //得到category_id的值
                    Integer categoryId = imageClassificationObject.optInt("category_id", -1);

                    if (categoryId==3){//若该值为3 表示反应过程图
                        label=1;
                    }else {//如果不是3 则从molclassifier中的label中获取该图的类型
                        JSONArray molclassifierArray = spansObject.optJSONArray("molclassifier");
                        if (molclassifierArray.length()!=0){
                            JSONObject molclassifierObject = molclassifierArray.getJSONObject(0);
                            String apiLabel = molclassifierObject.optString("label", "");
                            if (apiLabel.equals("Mechanism")){//反应机理图
                                label=2;
                            }else if (apiLabel.equals("experimental Result")){//实验结果图
                                label=3;
                            }else if (apiLabel.equals("Spectrum")){
                                label=4;
                            }
                        }
                    }
                }
            }
        }
        return Images.builder()
                .img(img)
                .label(label)
                .build();
    }

    /**
     * 已知type为image_caption 根据lines得到image的相关数据(caption)
     * @param lines
     * @return
     */
    public static Images lines2Caption(JSONArray lines){
        StringBuffer content=new StringBuffer();
        if (lines.length()!=0){
            JSONObject linesObject = lines.getJSONObject(0);//得到lines的json对象
            JSONArray spansArray = linesObject.optJSONArray("spans");//得到spans的json数组
            for (int i = 0; i < spansArray.length(); i++) {
                //遍历spans中的每一个json对象
                JSONObject spansObject = spansArray.getJSONObject(i);
                //获取每个对象的content值并拼接起来
                String subContent = spansObject.optString("content", "");
                content.append(subContent);
            }
        }
        return Images.builder()
                .caption(content.toString())
                .build();
    }

    /**
     * 已知type为image_footnote 根据lines得到image的相关数据(footnote)
     * @param lines
     * @return
     */
    public static Images lines2Footnote(JSONArray lines){
        StringBuffer content=new StringBuffer();
        if (lines.length()!=0){
            JSONObject linesObject = lines.getJSONObject(0);//得到lines的json对象
            JSONArray spansArray = linesObject.optJSONArray("spans");//得到spans的json数组
            for (int i = 0; i < spansArray.length(); i++) {
                //遍历spans中的每一个json对象
                JSONObject spansObject = spansArray.getJSONObject(i);
                //获取每个对象的content值并拼接起来
                String subContent = spansObject.optString("content", "");
                content.append(subContent);
            }
        }
        return Images.builder()
                .footnote(content.toString())
                .build();
    }

    private static CloseableHttpClient createHttpClient() throws IOException {
        try {
            // 创建一个不验证SSL证书的SSLContext
            SSLContext sslContext = SSLContextBuilder.create()
                    .loadTrustMaterial((chain, authType) -> true) // 允许所有证书
                    .build();

            return HttpClients.custom()
                    .setSSLContext(sslContext)
                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) // 不验证主机名
                    .build();
        } catch (Exception e) {
            throw new IOException("Failed to create HttpClient with SSL context", e);
        }
    }


    /**
     * 根据middle中的page_info中的数据 提取出所有base64编码图片
     * @param taskId
     * @param pdfInfoArray
     * @return
     */
    public static List<FormImg> middle2Imgs(Integer taskId, JSONArray pdfInfoArray) {
        List<FormImg> formImgList=new ArrayList<>();
        for(int i=0;i<pdfInfoArray.length();i++){
            //得到pdf_info中的每一个json对象
            JSONObject jsonObject = pdfInfoArray.getJSONObject(i);
            //得到tables数组
            JSONArray tablesJsonArray = jsonObject.optJSONArray("tables");
            if(tablesJsonArray!=null && tablesJsonArray.length()!=0){//若当前这个tables里面确实有东西
                //遍历得到tables里面每一个对象
                for(int j=0;j<tablesJsonArray.length();j++){
                    JSONObject tablesJsonObject = tablesJsonArray.getJSONObject(j);
                    JSONArray blocksJsonArray = tablesJsonObject.optJSONArray("blocks");
                    if (blocksJsonArray!=null && blocksJsonArray.length()!=0){//若当前blocks数组里面确实有东西
                        for (Object o1 : blocksJsonArray) {
                            JSONObject blocksObject = (JSONObject) o1;
                            JSONArray linesJsonArray = blocksObject.optJSONArray("lines");
                            if (linesJsonArray!=null && linesJsonArray.length()!=0){//若当前lines数组里面确实有东西
                                for (Object o2 : linesJsonArray) {
                                    JSONObject linesObject = (JSONObject) o2;
                                    JSONArray spansJsonArray = linesObject.optJSONArray("spans");
                                    if (spansJsonArray!=null && spansJsonArray.length()!=0){//若当前spans数组里面确实有东西
                                        for (Object o3 : spansJsonArray) {
                                            JSONObject spansObject = (JSONObject) o3;
                                            String imageBase64Str = spansObject.optString("image_base64_str", "");
                                            JSONArray bbox = spansObject.optJSONArray("bbox");
                                            String axis=bbox.toString();
                                            String[] str = axis.split("\\[");
                                            axis="["+(i+1)+","+str[1];
                                            if (!imageBase64Str.equals("")){
                                                FormImg formImg= FormImg.builder()
                                                        .taskId(taskId)
                                                        .img(imageBase64Str)
                                                        .axis(axis)
                                                        .build();
                                                formImgList.add(formImg);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return formImgList;
    }

    /**
     * 根据middle中的page_info中的数据 提取出所有html表格
     * @param taskId
     * @param pdfInfoArray
     * @return
     */
    public static List<FormTable> middle2Table(Integer taskId, JSONArray pdfInfoArray) {
        List<FormTable> formTableList=new ArrayList<>();
        for(int i=0;i<pdfInfoArray.length();i++){
            //得到pdf_info中的每一个json对象
            JSONObject jsonObject = pdfInfoArray.getJSONObject(i);
            JSONArray paraBlocksJSONArray = jsonObject.optJSONArray("para_blocks");
            if (paraBlocksJSONArray!=null && paraBlocksJSONArray.length()!=0){
                for (Object o1 : paraBlocksJSONArray) {
                    JSONObject paraBlocksJSONObject = (JSONObject) o1;
                    JSONArray blocksJSONArray = paraBlocksJSONObject.optJSONArray("blocks");
                    if (blocksJSONArray!=null && blocksJSONArray.length()!=0){
                        for (Object o2 : blocksJSONArray) {
                            JSONObject blocksJSONObject = (JSONObject) o2;
                            JSONArray linesJSONArray = blocksJSONObject.optJSONArray("lines");
                            if (linesJSONArray!=null && linesJSONArray.length()!=0){
                                for (Object o3 : linesJSONArray) {
                                    JSONObject linesJSONObject = (JSONObject) o3;
                                    JSONArray spansJSONArray = linesJSONObject.optJSONArray("spans");
                                    if (spansJSONArray!=null && spansJSONArray.length()!=0){
                                        for (Object o4 : spansJSONArray) {
                                            JSONObject spansJSONObject = (JSONObject) o4;
                                            String table = spansJSONObject.optString("html", "");
                                            if (!table.equals("")){
                                                FormTable formTable=new FormTable();
                                                formTable.setTaskId(taskId);
                                                formTable.setHtml(table);
                                                formTableList.add(formTable);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return formTableList;
    }


    /**
     * 调用api得到母核结构和实例分子的对应关系
     * @param markushList
     * @param numList
     * @return
     */
    public static String getMarAndNum(List<String> markushList,List<String> numList){
        String URL="https://lilab.ecust.edu.cn/nougat_predict/match_markush";
        Map<String,List<String>> paramMap=new HashMap<>();
        try (CloseableHttpClient client = createHttpClient()){
            HttpPost post = new HttpPost(URL);
            post.setHeader("Content-Type", "application/json");
            paramMap.put("markush_list",markushList);
            paramMap.put("instance_list",numList);
            Gson gson = new Gson();
            String json = gson.toJson(paramMap);
            post.setEntity(new StringEntity(json));
            HttpResponse response = client.execute(post);
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode==200) {//如果请求响应正确{
                BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
                StringBuilder responseBody = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    responseBody.append(line);
                }
                String res=responseBody.toString();
                return responseBody.toString();
            }else {
                throw new ServiceException(Constants.API_ERROR,"调用api失败");
            }
        }catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException(Constants.API_ERROR,"调用api失败");
        }
    }

    /**
     * 处理api返回中的content_list中的数据
     * steps:
     * - 先将母核结构插入数据库(主要为了获得id)
     * - 再调用api获取母核结构与实例分子的对应关系
     * - 将实例分子插入数据库
     * @param contentList
     *  api的content_list内容
     * @param taskId
     *  任务id
     */
    public static void dealMarAndNum(JSONArray contentList, Integer taskId){
        //构建numeratorPo的列表
        List<NumeratorPo> markushPoList = new ArrayList<>();
        List<NumeratorPo> smilesPoList=new ArrayList<>();
        //构建Markush列表
        List<String> markushList = new ArrayList<>();
        //构建实例分子列表
        List<String> instanceList = new ArrayList<>();

        for (int i = 0; i < contentList.length(); i++) {//得到contentList中每个json对象
            JSONObject contentJsonObject = contentList.getJSONObject(i);
            //"Markush_SMILES"或"SMILES"
            String markushStructure = contentJsonObject.optString("Markush_SMILES", "NOT A MARKUSH");
            Object flagSmiles = contentJsonObject.opt("SMILES");
            //如果是母核结构
            if (!"NOT A MARKUSH".equals(markushStructure)) {
                //加入Markush列表
                markushList.add(markushStructure);
                //为它构建一个NumeratorPo
                NumeratorPo numeratorPo = new NumeratorPo();
                markushPoList.add(numeratorPo);//将其加入列表
                numeratorPo.setStructure(markushStructure);
                numeratorPo.setIsMar(1);
                numeratorPo.setTaskId(taskId);
                JSONArray imgCaptionArray = contentJsonObject.optJSONArray("img_caption");
                numeratorPo.setNum(imgCaptionArray != null && imgCaptionArray.length()>0 ? imgCaptionArray.getString(0) : "");
                numeratorPo.setTrace(contentJsonObject.optInt("page_idx",-1)+1+"");
            }
            //如果是实例分子
            if (flagSmiles != null) {
                if (flagSmiles instanceof String) {//如果是一个分子
                    String smiles = contentJsonObject.optString("SMILES", "");
                    //加入实例分子列表
                    instanceList.add(smiles);
                    //为它构建一个NumeratorPo
                    NumeratorPo numeratorPo = new NumeratorPo();
                    smilesPoList.add(numeratorPo);//将其加入列表
                    numeratorPo.setStructure(smiles);
                    numeratorPo.setIsMar(0);
                    numeratorPo.setTaskId(taskId);
                    JSONArray imgCaptionArray = contentJsonObject.optJSONArray("img_caption");
                    numeratorPo.setNum(imgCaptionArray != null && imgCaptionArray.length()>0 ? imgCaptionArray.getString(0) : "");
                    numeratorPo.setTrace(contentJsonObject.optInt("page_idx",-1)+1+"");
                } else {//如果是分子列表
                    JSONArray smilesJsonArray = contentJsonObject.optJSONArray("SMILES");
                    for (int j = 0; j < smilesJsonArray.length(); j++) {//遍历这个分子列表
                        String smiles = smilesJsonArray.getString(j);
                        //加入实例分子列表
                        instanceList.add(smiles);
                        //为它构建一个NumeratorPo
                        NumeratorPo numeratorPo = new NumeratorPo();
                        smilesPoList.add(numeratorPo);//将其加入列表
                        numeratorPo.setStructure(smiles);
                        numeratorPo.setIsMar(0);
                        numeratorPo.setTaskId(taskId);
                        JSONArray imgCaptionArray = contentJsonObject.optJSONArray("img_caption");
                        numeratorPo.setNum(imgCaptionArray != null && imgCaptionArray.length()>0 ? imgCaptionArray.getString(0) : "");
                        numeratorPo.setTrace(contentJsonObject.optInt("page_idx",-1)+1+"");
                    }
                }
            }
        }

        //母核结构先插入数据库(因为我们需要它回显的id)
        if (markushPoList.size() != 0) {
            numeratorMapper.insert(markushPoList);//插入markush数据
        }
        //调用api获取对应结果
        String marAndNumResult = getMarAndNum(markushList, instanceList);
        JSONObject marAndNumResultJsonObject = new JSONObject(marAndNumResult);
        String marAndNumRes = marAndNumResultJsonObject.optString("result", "");
        if (!"".equals(marAndNumRes)) {//如果api调用的结果确实有值
            JSONObject resJsonObject = new JSONObject(marAndNumRes);
            //遍历得到所有key和value
            Iterator<String> keys = resJsonObject.keys();
            while (keys.hasNext()) {
                String jsonKey = keys.next(); // 获取键
                Object jsonValue = resJsonObject.get(jsonKey); // 获取值
                if (jsonValue != null) {//如果这个实例分子确实有对应的母核结构,那么我们就要进行匹配
                    String value = String.valueOf(jsonValue);
                    for (int i = 0; i < markushPoList.size(); i++) {
                        if (value.equals(markushPoList.get(i).getStructure())) {
                            for (int j = 0; j < smilesPoList.size(); j++) {
                                if (jsonKey.equals(smilesPoList.get(j).getStructure())) {
                                    smilesPoList.get(j).setBelongMar(markushPoList.get(i).getId());
                                }
                            }
                        }
                    }
                }
            }
        }


        //最后再将实例分子插入数据库
        if (smilesPoList.size()!=0) {
            numeratorMapper.insert(smilesPoList);//插入实例分子数据
        }
    }
}
